/**
 * 二维数组排列组合工具函数
 * @description 遍历二维数组，按照子数组的排列顺序进行组合，支持顺序或随机返回
 * @param {Array<Array>} twoDimensionalArray - 二维数组，每个子数组包含要组合的元素
 * @param {boolean} isOrdered - 状态参数，true表示按顺序返回，false表示随机打乱后返回
 * @returns {Array} 返回组合后的新数组
 * 
 * @example
 * // 示例1：按顺序组合
 * const arr = [['a', 'b'], ['1', '2'], ['x', 'y']];
 * const result = combineArrays(arr, true);
 * // 结果: [['a','1','x'], ['a','1','y'], ['a','2','x'], ['a','2','y'], ['b','1','x'], ['b','1','y'], ['b','2','x'], ['b','2','y']]
 * 
 * @example
 * // 示例2：随机组合
 * const arr = [['a', 'b'], ['1', '2'], ['x', 'y']];
 * const result = combineArrays(arr, false);
 * // 结果: 随机顺序的组合数组
 */
export function combineArrays(twoDimensionalArray, isOrdered = false) {
  // 参数验证
  if (!Array.isArray(twoDimensionalArray)) {
    throw new Error('第一个参数必须是数组');
  }
  
  if (twoDimensionalArray.length === 0) {
    return [];
  }
  
  // 早期验证：检查所有子数组并过滤掉空数组
  const validArrays = [];
  for (let i = 0; i < twoDimensionalArray.length; i++) {
    const subArray = twoDimensionalArray[i];
    if (!Array.isArray(subArray)) {
      throw new Error(`索引 ${i} 处的元素必须是数组`);
    }
    if (subArray.length === 0) {
      // 如果任何一个子数组为空，则无法形成有效组合
      return [];
    }
    validArrays.push(subArray);
  }
  
  // 计算总组合数，用于预分配数组大小
  const totalCombinations = validArrays.reduce((total, arr) => total * arr.length, 1);
  
  // 如果组合数过大，给出警告
  if (totalCombinations > 100000) {
    console.warn(`警告：将生成 ${totalCombinations} 个组合，这可能会消耗大量内存`);
  }
  
  // 使用更高效的算法：直接计算每个位置的值
  const combinations = new Array(totalCombinations);
  const arrayLengths = validArrays.map(arr => arr.length);
  
  for (let i = 0; i < totalCombinations; i++) {
    const combination = new Array(validArrays.length);
    let temp = i;
    
    // 从右到左计算每个位置的索引
    for (let j = validArrays.length - 1; j >= 0; j--) {
      const index = temp % arrayLengths[j];
      combination[j] = validArrays[j][index];
      temp = Math.floor(temp / arrayLengths[j]);
    }
    
    combinations[i] = combination;
  }
  
  // 如果需要随机打乱顺序
  if (!isOrdered) {
    return shuffleArray(combinations);
  }
  
  return combinations;
}

/**
 * 数组随机打乱函数（Fisher-Yates 洗牌算法）
 * @param {Array} array - 要打乱的数组
 * @returns {Array} 打乱后的新数组
 */
function shuffleArray(array) {
  if (!Array.isArray(array)) {
    throw new Error('shuffleArray 参数必须是数组');
  }
  
  if (array.length <= 1) {
    return array.slice(); // 对于空数组或单元素数组，直接返回副本
  }
  
  const shuffled = array.slice(); // 创建副本，避免修改原数组
  
  // 使用 Fisher-Yates 洗牌算法
  for (let i = shuffled.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    // 使用临时变量交换，比解构赋值更快
    const temp = shuffled[i];
    shuffled[i] = shuffled[j];
    shuffled[j] = temp;
  }
  
  return shuffled;
}

/**
 * 将组合结果转换为字符串数组
 * @description 将每个组合数组连接成字符串
 * @param {Array<Array>} combinations - 组合结果数组
 * @param {string} separator - 连接符，默认为空字符串
 * @returns {Array<string>} 字符串数组
 * 
 * @example
 * const combinations = [['a', '1', 'x'], ['a', '1', 'y']];
 * const result = combinationsToStrings(combinations);
 * // 结果: ['a1x', 'a1y']
 */
export function combinationsToStrings(combinations, separator = '') {
  return combinations.map(combination => combination.join(separator));
}

/**
 * 获取组合总数
 * @description 计算二维数组可能的组合总数
 * @param {Array<Array>} twoDimensionalArray - 二维数组
 * @returns {number} 组合总数
 * 
 * @example
 * const arr = [['a', 'b'], ['1', '2'], ['x', 'y']];
 * const count = getCombinationCount(arr);
 * // 结果: 8 (2 * 2 * 2)
 */
export function getCombinationCount(twoDimensionalArray) {
  if (!Array.isArray(twoDimensionalArray)) {
    throw new Error('参数必须是数组');
  }
  
  if (twoDimensionalArray.length === 0) {
    return 0;
  }
  
  let total = 1;
  const MAX_SAFE_COMBINATIONS = Number.MAX_SAFE_INTEGER;
  
  for (let i = 0; i < twoDimensionalArray.length; i++) {
    const subArray = twoDimensionalArray[i];
    
    if (!Array.isArray(subArray)) {
      throw new Error(`索引 ${i} 处的元素必须是数组`);
    }
    
    if (subArray.length === 0) {
      return 0; // 任何一个子数组为空，组合数为0
    }
    
    // 检查是否会发生数值溢出
    if (total > MAX_SAFE_COMBINATIONS / subArray.length) {
      throw new Error('组合数过大，超出了 JavaScript 安全整数范围');
    }
    
    total *= subArray.length;
  }
  
  return total;
}

// 默认导出主函数
export default combineArrays;